home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / COMMUNIC / 1572B.ZIP / KMT_IBM5.ZIP / MSSSER.ASM < prev    next >
Assembly Source File  |  1989-07-11  |  75KB  |  1,563 lines

  1.         NAME    mssser
  2. ; File MSSSER.ASM
  3. ; Edit history:
  4. ; Last edit 20 Jan 1989
  5. ; 20 Jan 1989 Correct Disable REM MESSAGE, and decoding of message.
  6. ; 21 Nov 1988 Version 2.32
  7. ; 10 Nov 1988 Clear flags.cxzflg when exiting server mode from Control-C.
  8. ; 1 Nov 1988 Add SET SERVER TIMEOUT control of NAKs in server idle loop.
  9. ; 16 Sept 1988 Add REMOTE LOGIN command for Terry Kennedy. Rewrite proc genric
  10. ;  to work with editing functions plus do prompts for login command. [jrd]
  11. ; 1 July 1988 Version 2.31
  12. ; 12 June 1988 Add error recovery if serial port does not initialize.
  13. ; 2 June 1988 Add timeout capability to Server command.
  14. ; 20 March 1988 Move ENABLE/DISABLE command to mssset, leave denyflg here.[jrd]
  15. ; 27 Jan 1988 Remove serrst call, done now in mssker idle loop. [jrd]
  16. ; 1 Jan 1988 version 2.30
  17.  
  18.         public  logout, bye, finish, remote, get, server, denyflg, srvtmo
  19.  
  20.         include mssdef.h
  21.  
  22. datas   segment public 'datas'
  23.         extrn   data:byte, flags:byte, trans:byte, pack:byte, curchk:byte
  24.         extrn   curdsk:byte, diskio:byte, locfil:byte, comand:byte, rptq:byte
  25.         extrn   filtst:byte, maxtry:byte, imxtry:byte, dtrans:byte,fmtdsp:byte
  26.         extrn   inichk:byte, errlev:byte, portval:word, fsta:word,kstatus:word
  27.  
  28. scrser  equ     0209H           ; place for server state display line
  29. scrsrm  equ     1000H           ; place for messages and dos echoes
  30.  
  31. remcmd  db      0               ; Remote command to be executed
  32. rempac  db      0               ; Packet type: C (host) or G (generic)
  33. remlen  db      0               ; length of following text field
  34.  
  35. ermes1  db      cr,lf,'?More parameters are needed$'
  36. ermes6  db      '?Filename too long for packet$'
  37. erms18  db      '?No response from host$'
  38. infms1  db      'Server mode: type Control-C to exit',cr,lf,'$'
  39. inthlp  db      cr,lf,' Time-limit to remain in Server mode, seconds or'
  40.         db      ' specific hh:mm:ss (24h clock).'
  41.         db      cr,lf,' SET TIMER ON to time.  Return for no time limit.$'
  42. remms1  db      'Kermit-MS Server: Unknown server command$'
  43. remms2  db      'Kermit-MS Server: Illegal file name$'
  44. remms3  db      'Kermit-MS Server: Could not create help file$'
  45. remms4  db      'Kermit-MS Server: Unable to change directories$'
  46. remms5  db      'Kermit-MS Server: No such file(s)$'
  47. remms6  db      'Kermit-MS Server: Could not create directory listing$'
  48. remms7  db      'Kermit-MS Server: Could not create space listing$'
  49. remms8  db      'Kermit-MS Server: Protected or no such file(s)$'
  50. remms9  db      'Kermit-MS Server: Command is Disabled$'
  51. remms10 db      'Kermit-MS Server: Could not create work file$'
  52. byemsg  db      'Kermit-MS Server:  Goodbye!',0
  53. whomsg  db      'Kermit-MS Server: Just this Server',0
  54. spcmsg  db      ' bytes available on disk',cr,lf,0
  55. spcmsg2 db      ' Drive not ready',cr,lf,0
  56. user    db      ' Username: $'          ; for Remote Login
  57. password db     ' Password: $'          ; for Remote Login and Remote CD
  58. account db      ' Account: $'           ; for Remote Login
  59. srvtmp  db      ' >$kermit$.tmp ',0     ; asciiz, kermit's temp output file
  60. delstr  db      'del ',0
  61. dirstr  db      'dir ',0
  62. crlf    db      cr,lf,'$'
  63. curstim db      ?                       ; normal waiting time for packets
  64. denyflg dw      0                       ; bit field of denied commands
  65. temp    dw      0
  66. inpbuf  dw      0                       ; Pointer to input buffer
  67. cnt     dw      0
  68. srvtmo  db      dstime                  ; idle NAKs, use default send timeout
  69. srvtime db      0                       ; non-zero if timing Server residence
  70. srvchr  db      'SRGIEC'                ; server cmd characters
  71. srvfln  equ     $-srvchr                ; length of table
  72. srvfun  dw      srvsnd,srvrcv,srvgen,srvini,rskp,srvhos ; order as in srvchr
  73.  
  74. remhlp  db      cr,lf,'CD/CWD     change working directory'     ; Answer to
  75.         db      cr,lf,'Delete     a file'                       ; local
  76.         db      cr,lf,'Directory  filespec'                     ; REM HELP
  77.         db      cr,lf,'Help'
  78.         db      cr,lf,'Host       command'
  79.         db      cr,lf,'Login      to remote Kermit server'
  80.         db      cr,lf,'Kermit     command'
  81.         db      cr,lf,'Message    short one line message'
  82.         db      cr,lf,'Space      in a directory'
  83.         db      cr,lf,'Type       a file'
  84.         db      cr,lf,'Who        user spec$'
  85.  
  86.                                         ; Answer from Server to REMOTE HELP
  87. hlprem  db      cr,lf,'Kermit-MS Server commands:',lf
  88.         db      cr,lf,'GET filespec             REMOTE DELETE filespec    '
  89.         db      'REMOTE MESSAGE message'
  90.         db      cr,lf,'SEND filespec            REMOTE DIRECTORY filespec '
  91.         db      'REMOTE SPACE'
  92.         db      cr,lf,'FIN, LOGO, and BYE       REMOTE HELP               '
  93.         db      'REMOTE TYPE filespec'
  94.         db      cr,lf,'REMOTE CD/CWD directory  REMOTE HOST command       '
  95.         db      'REMOTE WHO',0                          ; null terminated
  96.  
  97. remtab  db      12                      ; 12 entries
  98.         mkeyw   'CD',remcwd
  99.         mkeyw   'CWD',remcwd
  100.         mkeyw   'Delete',remdel
  101.         mkeyw   'Directory',remdir
  102.         mkeyw   'Help',remhel
  103.         mkeyw   'Host',remhos
  104.         mkeyw   'Kermit',remker
  105.         mkeyw   'Login',remlogin
  106.         mkeyw   'Message',remmsg
  107.         mkeyw   'Space',remdis
  108.         mkeyw   'Type',remtyp
  109.         mkeyw   'Who',remwho
  110.  
  111. remfnm  db      ' Remote Source File: $'
  112. lclfnm  db      ' Local Destination File: $'
  113. filhlp  db      ' File name to use locally$'
  114. filmsg  db      ' Remote filename or confirm with carriage return $'
  115. frem    db      ' Name of file on remote system $'
  116. genmsg  db      ' Enter text to be sent to remote server $'
  117. srvbuf  db      80H dup (0)
  118. rdbuf   db      20 dup (0)
  119. datas   ends
  120.  
  121. code    segment public 'code'
  122.         extrn comnd:near, serrst:near, spack:near, rpack:near, init:near
  123.         extrn read12:near, serini:near, read2:near, rpar:near, spar:near
  124.         extrn rin21:near, rfile3:near, error1:near, clrfln:near
  125.         extrn dodel:near, clearl:near, dodec: near, doenc:near
  126.         extrn packlen:near, send11:near, errpack:near, pktsize:near
  127.         extrn nak:near, rrinit:near, cmblnk:near, poscur:near, lnout:near
  128.         extrn erpos:near, rprpos:near, clrmod:near, crun:near, ctlu:near
  129.         extrn prompt:near, updrtr:near, prtfn:near, prtscr:near
  130.         extrn strcat:near, strlen:near, strcpy:near, fparse:near, isfile:near
  131.         extrn prtasz:near, ihosts:near, begtim:near, endtim:near
  132.         extrn inptim:near, chktmo:near, pcwait:near
  133.         assume  cs:code, ds:datas, es:nothing
  134.  
  135.  
  136. ; BYE command - tell remote KERSRV to logout & exits to DOS.
  137.  
  138. BYE     PROC    NEAR
  139.         mov     ah,cmcfm                ; Parse a confirm
  140.         call    comnd
  141.          jmp    r
  142.         mov     remcmd,'L'              ; Logout command letter
  143.         call    logo                    ; Tell the mainframe to logout
  144.          jmp    rskp                    ; Failed - don't exit
  145.         mov     flags.extflg,1          ; Set exit flag
  146.         jmp     rskp
  147. BYE     ENDP
  148.  
  149. ; FINISH - tell remote KERSRV to exit
  150.  
  151. FINISH  PROC    NEAR
  152.         mov     ah,cmcfm                ; Parse a confirm
  153.         call    comnd
  154.          jmp    r
  155.         mov     remcmd,'F'              ; Finish command letter
  156.         call    logo
  157.          jmp    rskp
  158.         jmp     rskp
  159. FINISH  ENDP
  160.  
  161. ; LOGOUT - tell remote KERSRV to logout
  162.  
  163. LOGOUT  PROC    NEAR
  164.         mov     ah,cmcfm
  165.         call    comnd                   ; Get a confirm
  166.          jmp    r
  167.         mov     remcmd,'L'              ; Logout command letter
  168.         call    logo
  169.          jmp    rskp                    ; Go get another command whether we
  170.         jmp     rskp                    ;  succeed or fail
  171. LOGOUT  ENDP
  172.  
  173. ; Common routine for FIN, LOGOUT, BYE
  174. LOGO    PROC    NEAR
  175.         mov     pack.numtry,0           ; Initialize count
  176.         mov     pack.numrtr,0           ; No retries yet
  177.         mov     ah,trans.chklen         ; Don't forget the checksum length
  178.         mov     curchk,ah
  179.         mov     trans.chklen,1          ; Use one char for server functions
  180.         call    serini                  ; Initialize port
  181.         jc      logo2                   ; c = failure
  182.         call    ihosts                  ; initialize the host
  183.         mov     diskio.string,0         ; clear local filename for stats
  184.         call    begtim                  ; start statistics counter
  185. logo1:  cmp     pack.state,'A'          ; Did user type a ^C?
  186.         je      log2x               ; e = yes, leave in failure state for Bye
  187.         mov     ah,pack.numtry
  188.         cmp     ah,maxtry               ; Too many times?
  189.         jl      logo3                   ; No, try it
  190. logo2:  mov     ah,prstr
  191.         mov     dx,offset erms18
  192.         int     dos
  193. log2x:;;;call   serrst                  ; Reset port
  194.         mov     ax,1                    ; a send operation
  195.         call    endtim                  ; stop statistics counter
  196.         mov     ah,curchk
  197.         mov     trans.chklen,ah         ; Restore value
  198.         ret                             ; and exit in failure state for Bye
  199. logo3:  inc     pack.numtry             ; Increment number of tries
  200.         mov     pack.seqnum,0           ; Packet number zero
  201.         mov     pack.datlen,1           ; One piece of data
  202.         mov     ah,remcmd               ; get command letter ('L' or 'F')
  203.         mov     data,ah                 ; Logout the remote host
  204.         mov     cx,1                    ; One piece of data
  205.         call    doenc                   ; Do encoding
  206.         mov     ah,'G'                  ; Generic command packet
  207.         call    spack
  208.          jmp    logo2                   ; Tell user and die
  209.          nop
  210.         call    rpack                   ; Get ACK (w/o screen msgs.)
  211.          jmp    logo1                   ; Go try again
  212.          nop
  213.         push    ax
  214.         call    dodec                   ; Decode packet
  215.         pop     ax
  216.         cmp     ah,'Y'                  ; ACK?
  217.         jne     logo4
  218.         cmp     pack.datlen,0           ; Any data in the ACK?
  219.         je      logo6                   ; Nope - just return.
  220.         mov     ah,prstr                ; output a cr/lf
  221.         mov     dx,offset crlf
  222.         int     dos
  223.         mov     di,offset data          ; Where the reply is
  224.         mov     cx,pack.datlen          ; How much data we have.
  225.         call    prtscr                  ; Print it on the screen
  226.         jmp     logo6                   ; and exit
  227. logo4:  cmp     ah,'E'                  ; Error packet?
  228.         je      logo5                   ; e = yes
  229.         jmp     logo1                   ; try sending again
  230. logo5:  call    error1
  231. logo6:  mov     ax,1                    ; a send operation
  232.         call    endtim                  ; stop statistics counter
  233.         mov     ah,curchk
  234.         mov     trans.chklen,ah         ; Restore value
  235.         jmp     rskp                    ; use rskp so Bye succeeds
  236. LOGO    ENDP
  237.  
  238. ; GET command. Ask remote server to send the specified file(s)
  239. ; Queries for remote filename and optional local override path/filename
  240. GET     PROC    NEAR
  241.         mov     flags.nmoflg,0          ; Reset flags from fn parsing
  242.         mov     byte ptr locfil,0       ; clear, for safety
  243.         mov     byte ptr srvbuf,0       ; ditto
  244.         mov     flags.cxzflg,0          ; no Control-C typed yet
  245.         mov     cnt,0                   ; count of filename chars
  246.         mov     bx,offset srvbuf        ; Where to put text
  247.         mov     byte ptr [bx],0         ; clear for safety
  248.         mov     dx,offset filmsg        ; In case user needs help
  249.         mov     ah,cmtxt                ; filenames with embedded whitespace
  250.         call    comnd                   ; Get text or confirm
  251.          jmp    r                       ; Fail
  252.         mov     al,ah
  253.         mov     ah,0
  254.         mov     cnt,ax                  ; Remember number of chars we read
  255.         cmp     al,0                    ; Read in any chars?
  256.         je      get1                    ; e = no
  257.         jmp     get3b                   ; yes, analyze
  258.                                         ; if empty line, ask for file names
  259. get1:   mov     dx,offset remfnm        ; ask for remote name first
  260.         call    prompt
  261.         mov     bx,offset srvbuf        ; place for remote filename
  262.         mov     dx,offset frem          ; the help message
  263.         mov     ah,cmtxt                ; use this for embedded spaces
  264.         call    comnd                   ; get a filename
  265.          jmp    r
  266.         mov     al,ah
  267.         mov     ah,0
  268.         mov     cnt,ax                  ; remember number of chars read
  269.         cmp     al,0                    ; count of entered chars
  270.         je      get1                    ; e = none, try again
  271. get2:   mov     dx,offset lclfnm        ; prompt for local filename
  272.         call    prompt
  273. get3:   mov     flags.nmoflg,0          ; assume no local override name
  274.         mov     bx,offset filhlp
  275.         mov     dx,offset locfil        ; complete local filename
  276.         mov     byte ptr locfil,0       ; clear, for safety
  277.         mov     ah,cmfile               ; allow paths
  278.         call    comnd
  279.          jmp    r
  280.         mov     temp,ax
  281.         mov     ah,cmcfm
  282.         call    comnd
  283.          jmp    r
  284.         mov     ax,temp
  285.         cmp     ah,0                    ; any text?
  286.         je      get2                    ; e = none, ask again
  287.         mov     bx,offset locfil
  288.         cmp     byte ptr [bx],'#'       ; Is first char a replacement for '?'
  289.         jne     get3a                   ; ne = no
  290.         mov     byte ptr [bx],'?'       ; yes. Replace '#' by '?'
  291. get3a:  mov     al,ah           ; number of chars in locfil according to cmd
  292.         mov     flags.nmoflg,al         ; 0 = no override
  293.         mov     ah,0
  294.         add     bx,ax
  295.         mov     byte ptr [bx],0         ; force a termination null
  296.  
  297. get3b:  mov     bx,offset srvbuf        ; get remote filename address again
  298.         cmp     byte ptr [bx],'#'       ; Is first char a replacement for '?' ?
  299.         jne     get4                    ; ne = no
  300.         mov     byte ptr [bx],'?'       ; yes. Replace '#' by '?'
  301.  
  302. get4:   cmp     flags.cxzflg,0          ; ~X, ^Z, or ^C typed?
  303.         je      get5                    ; e = no, keep going
  304.         mov     flags.cxzflg,0          ; clear the interrupt flag
  305.         or      errlev,2                ; say cannot receive
  306.         or      fsta.xstatus,2+80h      ; set status failed + intervention
  307.         mov     kstatus,2               ; local status
  308.         jmp     rskp
  309. get5:   call    begtim                  ; start statistics
  310.         cmp     flags.destflg,2         ; receiving to screen?
  311.         je      get5a                   ; e = yes, skip screen stuff
  312.         mov     flags.xflg,0            ; no, reset x flag
  313.         call    init                    ; init screen
  314. get5a:  call    begtim                  ; start statistics
  315.         mov     kstatus,0               ; global status, success
  316.         call    ipack                   ; Send Initialize, 'I', packet
  317.          jmp    get8                    ; Sorry can't do it
  318.          nop
  319.         mov     cx,cnt                  ; Get back remote filename size
  320.         mov     pack.datlen,cx          ; Need it here to send packet
  321.         mov     si,offset srvbuf        ; Move from here
  322.         mov     di,offset data          ; to here
  323.         call    strcpy                  ; copy from srvbuf to data
  324.         mov     di,offset fsta.xname    ; to statistics remote name field
  325.         call    strcpy
  326.         mov     di,offset diskio.string ; and to here for prtfn
  327.         call    strcpy
  328.         test    flags.remflg,dquiet     ; quiet display mode?
  329.         jnz     get6                    ; nz = yes, don't print anything
  330.         cmp     flags.remflg,dserial    ; serial mode display?
  331.         je      get6                    ; e = yes, skip extra display item
  332.         cmp     flags.destflg,2         ; Receiving to screen?
  333.         je      get6                    ; Yes skip screen stuff
  334.         call    prtfn                   ; print filename in data
  335. get6:
  336.         call    rrinit                  ; clear pack.xxx counters
  337.         mov     pack.numrtr,-1  ; No retries yet (gets incremented below)
  338.         mov     pack.state,'R'          ; this is what state will be soon
  339.         mov     cx,pack.datlen          ; Data size
  340.         call    doenc                   ; Encode data
  341.         jnc     get6a                   ; nc = success
  342.         jmp     get12           ; c = data could not all fit into packet
  343. get6a:  mov     ah,trans.chklen         ; Don't forget the checksum length
  344.         mov     curchk,ah
  345.         mov     trans.chklen,1          ; Use one char for server functions
  346. get7:   call    updrtr
  347.         cmp     pack.state,'A'          ; Did user type a ^C?
  348.         je      get9                    ; Yes - just return to main loop
  349.         mov     ah,pack.numtry
  350.         cmp     ah,maxtry               ; Too many times?
  351.         jbe     get10                   ; Nope, try it
  352. get8:   test    flags.remflg,dquiet     ; quiet display mode?
  353.         jnz     get9                    ; nz = yes, no printing
  354.         call    erpos
  355.         mov     ah,prstr
  356.         mov     dx,offset erms18        ; Can't get init packet.
  357.         int     dos
  358.         or      errlev,2                ; set DOS error level to cannot rcv
  359.         or      fsta.xstatus,2          ; set status
  360.         mov     kstatus,2               ; global status
  361. get9:   test    flags.remflg,dquiet+dserial ; quiet or serial display?
  362.         jnz     get9a                   ; nz = yes
  363.         call    clrmod
  364.         call    rprpos
  365. get9a:  mov     ah,curchk
  366.         mov     trans.chklen,ah         ; Restore value
  367.         xor     ax,ax                   ; say this was a receive operation
  368.         call    endtim                  ; do statistics
  369.         jmp     rskp
  370. get10:  inc     pack.numtry             ; Increment number of tries
  371.         mov     pack.seqnum,0           ; Start at packet zero
  372.         call    pktsize                 ; report packet size
  373.         mov     ah,'R'                  ; Receive init packet
  374.         call    spack                   ; Send the packet
  375.          jmp    get8                    ; Tell user we can't do it
  376.          nop
  377.         call    rpack                   ; Get ACK
  378.          jmp    get7                    ; Got a NAK - try again
  379.          nop
  380.         push    ax
  381.         mov     ah,curchk
  382.         mov     trans.chklen,ah         ; Restore value
  383.         pop     ax
  384.         mov     flags.getflg,ah         ; note this is a GET, use pkt type
  385.         mov     pack.state,'R'          ; Set the state to receive initiate
  386.         jmp     read12                  ; go join read code
  387. get12:  mov     dx,offset ermes6    ; Complain if filename is too long for pkt
  388.         test    flags.remflg,dquiet     ; quiet display mode?
  389.         jnz     get13                   ; nz = yes, no printing
  390.         call    erpos                   ; position cursor on formatted screen
  391.         mov     ah,prstr
  392.         int     dos
  393. get13:  mov     bx,dx                   ; point to message, for errpack
  394.         call    errpack                 ; tell the host we are quiting
  395.         test    flags.remflg,dserial    ; serial display mode?
  396.         jnz     get14                   ; nz = yes
  397.         call    clrmod                  ; clear mode line
  398.         call    rprpos                  ; Put prompt here
  399. get14:  or      errlev,2                ; set DOS error level to cannot rcv
  400.         or      fsta.xstatus,2          ; set status
  401.         mov     kstatus,2               ; global status
  402.         jmp     rskp
  403. GET     ENDP
  404.  
  405. ; server command
  406.  
  407. SERVER  PROC    NEAR
  408.         mov     ah,cmfile               ; get a word
  409.         mov     dx,offset srvbuf        ; place to put text
  410.         mov     bx,offset inthlp        ; help message
  411.         call    comnd                   ; get the pattern text
  412.          jmp    r                       ; nothing, complain
  413.          nop
  414.         mov     temp,ax                 ; ah has byte count
  415.         mov     ah,cmcfm
  416.         call    comnd
  417.          jmp    r
  418.         mov     srvtime,0               ; assume not doing timed residence
  419.         cmp     byte ptr temp+1,0       ; time of day given?
  420.         je      serv0b                  ; e = no
  421.         mov     si,offset srvbuf
  422.         cmp     byte ptr [si],'0'       ; numeric or colon?
  423.         jb      serv0                   ; b = not proper time value
  424.         cmp     byte ptr [si],':'       ; this covers the desired range
  425.         ja      serv0                   ; a = no proper time value
  426.         call    inptim                  ; convert text to timeout tod
  427.         jnc     serv0a                  ; nc = no syntax errors in time
  428. serv0:  ret                             ; else return now
  429.  
  430. serv0a: mov     srvtime,1               ; say doing timed residence
  431. serv0b: push    es
  432.         mov     ax,ds
  433.         mov     es,ax                   ; address data segment
  434.         mov     al,flags.remflg         ; get display mode flag
  435.         push    ax                      ; preserve for later
  436. ; Enable the line below if the server screen is to be quiet (clear),
  437. ; or make the line a comment if the server screen is to show file transfers
  438. ;===>   mov     flags.remflg,dquiet     ; set quiet display flag if server
  439.                                         ;
  440.         or      flags.remflg,dserver    ; signify we are a server now
  441.         mov     ax,0                    ; simulate empty parameter packet
  442.         call    spar                    ; and thus set our params to defaults
  443.         mov     ah,drpt                 ; force default repeat prefix char
  444.         mov     rptq,ah                 ;  char be our active one
  445.         test    flags.remflg,dquiet     ; quiet display?
  446.         jnz     serv1c                  ; nz = yes
  447.         mov     ah,prstr
  448.         mov     dx,offset crlf
  449.         int     dos
  450.         test    flags.remflg,dserial    ; serial display?
  451.         jnz     serv1a                  ; nz = yes
  452.         call    cmblnk                  ; clear screen
  453.         mov     dx,scrser               ; move cursor to top of screen
  454.         call    poscur
  455. serv1a: mov     ah,prstr
  456.         mov     dx,offset infms1        ; say now in server mode
  457.         int     dos
  458. serv1c: mov     ah,inichk               ; set default checksum length
  459.         mov     curchk,ah               ; save it here
  460.  
  461. serv1:  test    flags.remflg,dquiet+dserial ; quiet or serial display?
  462.         jnz     serv1b                  ; nz = yes
  463.         mov     dx,scrsrm               ; move cursor to server message area
  464.         add     dx,0100H        ; look at line below (DOS does CR/LF first)
  465.         call    poscur
  466.         call    clearl                  ; and clear the line
  467.         mov     dx,scrsrm               ; back to message line
  468.         call    poscur
  469.         cmp     flags.debug,0           ; debug display active?
  470.         je      serv1b                  ; e = no
  471.         mov     fmtdsp,1                ; yes, do formatted display
  472. serv1b: mov     flags.nmoflg,0  ; clear, say no local override filenames
  473.         mov     flags.cxzflg,0          ; clear ^X, ^Z, ^C seen flag
  474.         mov     flags.xflg,0            ; reset X packet flag
  475.         mov     locfil,0                ; say no local filename [JB]
  476.         mov     ah,dtrans.seol          ; restore default end-of-line char
  477.         mov     trans.seol,ah
  478.         mov     byte ptr srvbuf,0       ; plant terminator to clear
  479.         mov     trans.chklen,1          ; checksum len = 1
  480.         mov     pack.pktnum,0           ; pack number resets to 0
  481.         mov     pack.numtry,0           ; no retries yet
  482.         mov     al,trans.stime          ; get current timeout interval
  483.         mov     curstim,al              ; save current timeout interval
  484.         add     al,al                   ; triple it for server idle loop
  485.         add     al,curstim              ; times three
  486.         mov     trans.stime,al  ;  use this longer interval in the idle loop
  487.         call    serini          ; init serial line (send & receive reset it)
  488.         jnc     serv1e                  ; nc = success
  489.         jmp     serv5                   ; c = failure
  490. serv1e: cmp     srvtime,0               ; doing timed residence?
  491.         je      serv1d                  ; e = no
  492.         call    chktmo                  ; check for time to exit Server mode
  493.         jnc     serv1d                  ; nc = ok
  494.         jmp     serv5                   ; c = timeout, exit server mode
  495. serv1d: call    rpack                   ; get a packet
  496.          jmp    short serv2             ; no good, nak and continue
  497.          nop
  498.         push    ax
  499.         mov     al,curstim              ; get original timeout interval
  500.         mov     trans.stime,al          ; restore timeout interval
  501.         pop     ax
  502.         cmp     ah,'I'                  ; never "decode" S, I, and A packets
  503.         je      serv3                   ; its an I packet
  504.         cmp     ah,'S'
  505.         je      serv3
  506.         cmp     ah,'A'
  507.         je      serv3
  508.         call    dodec                   ; decode packet
  509.         jmp     short serv3             ; try to figure this out
  510.  
  511. serv2:  push    ax
  512.         mov     al,curstim              ; get original timeout interval
  513.         mov     trans.stime,al          ; restore timeout interval
  514.         pop     ax
  515.         cmp     flags.cxzflg,'C'        ; Control-C?
  516.         jne     serv2a                  ; ne = no
  517.         mov     flags.cxzflg,0          ; clear flag for later uses
  518.         jmp     serv5                   ; and exit server mode
  519. serv2a: cmp     ah,'T'                  ; packet type of time-out?
  520.         jne     serv2b                  ; ne = no
  521.         mov     al,srvtmo               ; server timeout value
  522.         mov     trans.stime,al
  523.         call    nak                     ; nak the packet
  524.         mov     al,curstim
  525.         mov     trans.stime,al          ; restore regular send timeout
  526. serv2b: mov     al,curchk               ; restore checksum length
  527.         mov     trans.chklen,al
  528.         jmp     serv1                   ; and keep readiserv2 packets
  529.  
  530. serv3:  mov     al,curchk               ; restore checksum length
  531.         mov     trans.chklen,al
  532.         push    ds
  533.         pop     es                      ; set es to datas segment
  534.         mov     di,offset srvchr        ; server characters
  535.         mov     cx,srvfln               ; length of striserv2
  536.         mov     al,ah                   ; packet type
  537.         cld
  538.         repne   scasb                   ; hunt for it
  539.         je      serv4                   ; we know this one, go handle it
  540.         cmp     al,'N'                  ; received a Nak?
  541.         je      serv3a                  ; e = yes, ignore it
  542.         mov     bx,offset remms1        ; else give a message
  543.         call    errpack                 ; back to local kermit
  544. serv3a: jmp     serv1                   ; and keep lookiserv2 for a cmd
  545. serv4:  sub     di,offset srvchr+1      ; find offset, +1 for pre-increment
  546.         shl     di,1                    ; convert to word index
  547.         call    srvfun[di]              ; call the appropriate handler
  548.          jmp    serv5                   ; someone wanted to exit..
  549.         jmp     serv1                   ; else keep goiserv2 for more cmds
  550.  
  551. serv5:  mov     al,curchk               ; restore checksum length
  552.         mov     trans.chklen,al
  553.         pop     ax                      ; get this off stack
  554.         test    flags.remflg,dserial+dquiet ; serial or quiet display?
  555.         jnz     serv5a                  ; nz = yes
  556.         call    rprpos                  ; Put prompt here
  557. serv5a: mov     flags.remflg,al         ; restore old flag
  558. ;;      call    serrst                  ; reset serial handler
  559.         mov     fmtdsp,0                ; end of formatted display
  560.         mov     flags.cxzflg,0          ; clear this flag before exiting
  561.         pop     es                      ; restore register
  562.         jmp     rskp                    ; and return
  563. SERVER  ENDP
  564.  
  565. ; server commands
  566.  
  567. ; srvsnd - receives a file that a remote kermit is sending
  568. srvsnd  proc    near
  569.         mov     bx,offset data
  570.         mov     ax,pack.datlen          ; get number of data bytes
  571.         call    spar                    ; parse the send-init packet
  572.         mov     al,trans.chklen         ; get negotiated checksum length
  573.         mov     curchk,al               ;  and remember it here
  574.         call    packlen                 ; figure max packet
  575.         mov     bx,offset data
  576.         call    rpar                    ; make answer for them
  577.         mov     al,ah                   ; length of packet
  578.         mov     ah,0
  579.         mov     pack.datlen,ax          ; store length for spack
  580.         mov     trans.chklen,1          ; reply with 1 char checksum
  581.         call    pktsize                 ; report packet size
  582.         mov     ah,'Y'                  ; ack
  583.         call    spack                   ; answer them
  584.          jmp    rskp                    ; can't answer, forget this
  585.         mov     al,curchk               ; restore checksum length
  586.         mov     trans.chklen,al
  587.         call    rrinit                  ; init variables for init
  588.         cmp     flags.destflg,2         ; file destination = screen?
  589.         jne     srvsnd0                 ; ne = no
  590.         mov     flags.xflg,1            ; say receiving to screen
  591.         jmp     srvsnd1
  592. srvsnd0:call    init                    ; setup display form
  593. srvsnd1:mov     si,offset srvbuf        ; work buffer
  594.         mov     byte ptr[si],5ch        ; backslash
  595.         inc     si
  596.         mov     ah,gcd                  ; get current directory (path really)
  597.         xor     dl,dl                   ; use current drive
  598.         int     dos             ; returns ds:si with asciiz path (no drive)
  599.         mov     si,offset srvbuf
  600.         mov     di,offset locfil        ; destination is local override name
  601.         call    strcpy                  ; copy the path to local filename
  602.         mov     dx,di
  603.         call    strlen                  ; get length of string into cx
  604.         mov     di,cx                   ; length of local path
  605.         mov     locfil[di],5ch          ; add backslash
  606.         mov     locfil[di+1],0          ; null terminator
  607.         mov     flags.nmoflg,1  ; say have override name (zaps external path)
  608.         inc     pack.pktnum             ; count the send-init packet
  609.         mov     pack.state,'F'          ; expecting file name about now
  610.         call    read12                  ; join read code. changed from read2
  611.          nop
  612.          nop
  613.          nop                            ; ignore errors
  614.         mov     flags.xflg,0
  615.         jmp     rskp                    ; and return for more
  616. srvsnd  endp
  617.  
  618. ; srvrcv - send a file to a distant kermit
  619.  
  620. srvrcv  proc    near
  621.         mov     si,offset data          ; received filename, asciiz from rpack
  622.         test    denyflg,getsflg         ; command enabled?
  623.         jz      srrcv2                  ; z = yes
  624.         mov     di,offset srvbuf        ; local path
  625.         mov     si,offset rdbuf         ; local filename
  626.         mov     dx,offset data          ; local string
  627.         call    fparse                  ; split string
  628.         mov     si,offset rdbuf         ; copy local filename to
  629. srrcv2: mov     di,offset diskio.string ; destination
  630.         call    strcpy                  ; copy data to diskio.string
  631.         mov     pack.state,'R'          ; remember state
  632.         call    send11                  ; this should send it
  633.          jmp    rskp
  634.         jmp     rskp                    ; return in any case
  635. srvrcv  endp
  636.  
  637. ; srvgen - G generic server command dispatcher
  638. ;
  639. srvgen  proc    near
  640.         mov     al,data                 ; get 1st packet char
  641. srvge2: cmp     al,'T'                  ; Type a file?
  642.         jne     srvge3                  ; ne = no
  643.         call    srvtyp                  ; do the typing
  644.         jmp     rskp
  645. srvge3: cmp     al,'D'                  ; do a directory?
  646.         jne     srvge4
  647.         call    srvdir                  ; do the directory command
  648.         jmp     rskp
  649. srvge4: cmp     al,'E'                  ; do a file erase (delete)?
  650.         jne     srvge5
  651.         call    srvdel                  ; do the delete command
  652.         jmp     rskp
  653. srvge5: cmp     al,'C'                  ; change working dir?
  654.         jne     srvge6                  ; ne = no
  655.         call    srvcwd                  ; do it
  656.         jmp     rskp
  657. srvge6: cmp     al,'U'                  ; do a space command?
  658.         jne     srvge7
  659.         call    srvspc                  ; do the space command
  660.         jmp     rskp
  661. srvge7: cmp     al,'F'                  ; FIN?
  662.         jne     srvge8                  ; ne = no
  663.         jmp     srvfin
  664. srvge8: cmp     al,'L'                  ; LOGO or BYE?
  665.         jne     srvge9                  ; ne = no
  666.         call    srvfin
  667.          jmp    short srvge8a           ; permitted to exit Kermit
  668.          nop
  669.         jmp     rskp                    ; stay active (command denied)
  670. srvge8a:mov     flags.extflg,1          ; set exit flag
  671.         ret                             ; leave server mode and Kermit
  672. srvge9: cmp     al,'M'                  ; one line Message?
  673.         jne     srvge10                 ; ne = no
  674.         call    srvsen
  675.         jmp     rskp
  676. srvge10:cmp     al,'W'                  ; WHO?
  677.         jne     srvge11                 ; ne = no
  678.         call    srvwho
  679.         jmp     rskp
  680. srvge11:cmp     al,'H'                  ; Help?
  681.         jne     srvgex                  ; ne = no
  682.         jmp     srvhlp
  683. srvgex: mov     bx,offset remms1        ; reply Unknown server command
  684.         mov     trans.chklen,1          ; reply with 1 char checksum
  685.         call    errpack
  686.         jmp     rskp
  687. srvgen  endp
  688.  
  689. ; srvfin - respond to remote host's Fin command. [jrd]
  690. srvfin  proc    near
  691.         test    denyflg,finflg          ; command enabled?
  692.         jz      srfin1                  ; z = yes
  693.         mov     bx,offset remms9        ; else give a message
  694.         mov     trans.chklen,1          ; reply with 1 char checksum
  695.         call    errpack                 ; back to local kermit
  696.         jmp     rskp                    ; stay in server mode
  697. srfin1: mov     si,offset byemsg        ; add brief msg of goodbye
  698.         mov     di,offset data          ; packet's data field
  699.         call    strcpy                  ; copy msg to pkt
  700.         mov     dx,si                   ; strlen works on dx
  701.         call    strlen
  702.         mov     ah,'Y'                  ; reply with an ack
  703.         mov     pack.datlen,cx          ; length
  704.         mov     trans.chklen,1          ; reply with 1 char checksum
  705.         call    pktsize                 ; report packet size
  706.         call    spack                   ; send it, expect no response
  707.          nop                            ; ignore errors
  708.          nop
  709.          nop
  710.         mov     ax,100                  ; wait 0.1 sec for client to settle
  711.         call    pcwait
  712.         ret                             ; ret exits server mode
  713. srvfin  endp
  714.  
  715. ; srvcwd - handle other side's Remote CWD dirspec [jrd]
  716. srvcwd  proc    near
  717.         test    denyflg,cwdflg          ; is command enabled?
  718.         jz      srcwd4                  ; z = yes
  719.         mov     bx,offset remms9        ; else give a message
  720.         mov     trans.chklen,1          ; reply with 1 char checksum
  721.         call    errpack                 ; back to local kermit
  722.         ret
  723. srcwd4: cmp     pack.datlen,1           ; any data?
  724.         je      srcwd3                  ; e = no
  725.         mov     cl,data+1               ; get the filename byte count
  726.         sub     cl,' '                  ; ascii to numeric
  727.         mov     ch,0                    ; set up counter
  728.         cmp     cl,0                    ; anything there?
  729.         jle     srcwd3                  ; le = no, an error
  730.         mov     si,offset data+2        ; received dir spec, from rpack
  731.         mov     di,offset srvbuf        ; destination
  732.         push    es                      ; save es
  733.         push    ds
  734.         pop     es                      ; make es:di point to datas segment
  735.         cld
  736.         rep movsb                       ; copy data to srvbuf, cx chars worth
  737.         pop     es
  738.         mov     byte ptr [di],0         ; plant terminator
  739.         mov     dx,offset srvbuf        ; for DOS
  740.         mov     ax,dx                   ; dir spec pointer for isfile
  741.         cmp     byte ptr [di-1],':'     ; did user just type A: or similar?
  742.         je      srcwd1                  ; e = yes, so skip directory part
  743.         mov     ah,chdir                ; want to do change dir
  744.         int     dos
  745.         jnc     srcwd1                  ; nc = ok
  746. srcwd3: mov     bx,offset remms4        ; an error
  747.         mov     trans.chklen,1          ; reply with 1 char checksum
  748.         call    errpack                 ; send the bad news
  749.         ret
  750. srcwd1: mov     dl,data+3               ; see if drive given (look for :)
  751.         cmp     dl,':'
  752.         jne     srcwd2                  ; ne = no drive
  753.         mov     dl,data+2
  754.         and     dl,5fH                  ; convert to upper case
  755.         sub     dl,'A'                  ; count A = 0 for seldsk call
  756.         mov     ah,seldsk
  757.         int     dos                     ; change disks
  758.         jc      srcwd3                  ; c = an error
  759.         inc     dl                      ; now make A = 1 etc internally
  760.         mov     curdsk,dl               ;and update internal current disk code
  761. srcwd2: mov     ah,'Y'                  ; return an ack
  762.         mov     pack.datlen,0           ; no data
  763.         mov     trans.chklen,1          ; reply with 1 char checksum
  764.         call    pktsize                 ; report packet size
  765.         call    spack
  766.          nop
  767.          nop
  768.          nop
  769.         ret
  770. srvcwd  endp
  771.  
  772. ; srvtyp - handle other side's Remote Type filename request [jrd]
  773. ; expects "data" to hold  Tcfilename   where c = # bytes in filename
  774. srvtyp  proc    near
  775.         cmp     pack.datlen,1           ; any data in packet
  776.         je      srtyp2                  ; e = no
  777.         mov     cl,data+1               ; get the filename byte count
  778.         sub     cl,' '                  ; ascii to numeric
  779.         mov     ch,0                    ; set up counter
  780.         mov     si,offset data+2        ; received filename, asciiz from rpack
  781.         mov     di,si
  782.         add     di,cx
  783.         mov     byte ptr [di],0         ; make string asciiz
  784.         test    denyflg,typflg          ; paths permitted?
  785.         jz      srtyp1                  ; z = yes, else use just filename part
  786.         mov     di,offset srvbuf        ; local path
  787.         mov     si,offset rdbuf         ; local filename
  788.         mov     dx,offset data+2        ; local string
  789.         call    fparse                  ; split string
  790.         mov     si,offset rdbuf         ; copy local filename to
  791. srtyp1: mov     di,offset diskio.string ; destination
  792.         call    strcpy                  ; do the copy
  793.         mov     ax,offset diskio.string ; pointer to filename, for isfile
  794.         call    isfile                  ; does it exist?
  795.         jnc     srtyp3                  ; nc = yes
  796. srtyp2: mov     bx,offset remms5        ; "No such file(s)"
  797.         mov     trans.chklen,1          ; reply with 1 char checksum
  798.         call    errpack                 ; send error message
  799.         ret                             ; and exit
  800. srtyp3: mov     flags.xflg,1            ; say use X packet rather than F pkt
  801.         mov     pack.state,'R'          ; remember state
  802.         call    send11                  ; this should send it
  803.          nop
  804.          nop
  805.          nop
  806.         mov     flags.xflg,0            ; clear flag
  807.         ret                             ; return in any case
  808. srvtyp  endp
  809.  
  810. ; serdir - handle other side's Remote Dir filespec(optional) request [jrd]
  811. srvdir  proc    near
  812.         mov     cx,0                    ; assume no data in packet
  813.         cmp     pack.datlen,1           ; any data in the packet?
  814.         je      srdir4                  ; e = no
  815.         mov     cl,data+1               ; get the filename byte count
  816.         sub     cl,' '                  ; ascii to numeric
  817.         mov     ch,0                    ; set up counter
  818. srdir4: mov     di,offset data+2        ; received filespec, asciiz from rpack
  819.         add     di,cx
  820.         mov     byte ptr [di],0         ; make string asciiz
  821.         test    denyflg,dirflg          ; paths permitted?
  822.         jz      srdir1                  ; z = yes, else use just filename part
  823.         mov     di,offset srvbuf        ; local path
  824.         mov     si,offset rdbuf         ; local filename
  825.         mov     dx,offset data+2        ; local string
  826.         call    fparse                  ; split string
  827.         mov     si,offset rdbuf         ; copy local filename to
  828.         mov     di,offset data+2        ; final filename
  829.         call    strcpy                  ; do the copy
  830.         mov     ax,di
  831.         call    isfile                  ; is/are there any such file?
  832.         jc      srdir1                  ; c = there is none
  833.         test    byte ptr filtst.dta+21,1EH ; attr bits: is file protected?
  834.         jz      srdir1                  ; z = not protected
  835.         mov     bx,offset remms8        ; "Protected or no such file(s)"
  836.         mov     trans.chklen,1          ; reply with 1 char checksum
  837.         call    errpack                 ; send error message
  838.         ret                             ; and exit
  839.  
  840. srdir1: mov     di,offset srvbuf        ; work area
  841.         mov     si,offset dirstr        ; prepend "dir "
  842.         call    strcpy
  843.         mov     si,offset data+2        ; directory spec, asciiz
  844.         mov     di,offset srvbuf
  845.         call    strcat
  846.         mov     si,offset srvtmp    ; add redirection tag of " >$kermit$.tmp"
  847.         mov     di,offset srvbuf
  848.         call    strcat
  849.         mov     si,offset srvbuf        ; command pointer for crun
  850.         call    crun
  851.          nop
  852.          nop
  853.          nop
  854.         mov     si,offset srvtmp+2      ; get name of temp file
  855.         mov     di,offset diskio.string ; destination
  856.         call    strcpy                  ; copy it there
  857.         mov     ax,di                   ; filename pointer for isfile
  858.         call    isfile                  ; did we make the temp file?
  859.         jnc     srdir3                  ; nc = yes
  860.         mov     bx,offset remms6        ; "Could not create directory listing"
  861.         mov     trans.chklen,1          ; reply with 1 char checksum
  862.         call    errpack                 ; send the error message
  863.         ret                             ; and exit
  864. srdir3: mov     flags.xflg,1            ; say use X rather than F packet
  865.         mov     pack.state,'R'          ; remember state
  866.         call    send11                  ; this should send it
  867.          nop
  868.          nop
  869.          nop
  870.         mov     flags.xflg,0            ; clear flag
  871.         mov     dx,offset diskio.string
  872.         mov     ah,del2                 ; delete the file
  873.         int     dos
  874.         ret                             ; return in any case
  875. srvdir  endp
  876.  
  877. ; serdel - handle other side's request of Remote Del filespec [jrd]
  878. srvdel  proc    near
  879.         test    denyflg,delflg          ; command enabled?
  880.         jz      srvdel4                 ; z = yes
  881.         mov     bx,offset remms9        ; else give a message
  882.         mov     trans.chklen,1          ; reply with 1 char checksum
  883.         call    errpack                 ; back to local kermit
  884.         ret
  885.  
  886. srvdel4:cmp     pack.datlen,1           ; any data?
  887.         je      srdel1                  ; e = no
  888.         mov     di,offset srvbuf        ; work area
  889.         mov     si,offset delstr        ; prepend "del "
  890.         call    strcpy
  891.         mov     dx,offset srvbuf
  892.         call    strlen
  893.         add     di,cx                   ; di points at terminator
  894.         mov     ax,di                   ; save pointer to incoming filespec
  895.         mov     cl,data+1               ; get the filename byte count
  896.         sub     cl,' '                  ; ascii to numeric
  897.         mov     ch,0                    ; set up counter
  898.         cmp     cl,0                    ; anything there?
  899.         jle     srdel3                  ; le = no
  900.         mov     si,offset data+2        ; received filespec, asciiz from rpack
  901.         push    es                      ; save es
  902.         push    ds
  903.         pop     es                      ; set es to datas segment
  904.         cld
  905.         rep     movsb                   ; append data to srvbuf
  906.         pop     es                      ; restore es
  907.         mov     byte ptr [di],0         ; plant terminator
  908.         call    isfile                  ; is/are there any to delete?
  909.         jc      srdel1                  ; c = there is none
  910.         test    byte ptr filtst.dta+21,1EH ; attr bits: is file protected?
  911.         jz      srdel2                  ; z = not protected
  912. srdel1: mov     bx,offset remms8        ; "Protected or no such file(s)"
  913.         mov     trans.chklen,1          ; reply with 1 char checksum
  914.         call    errpack                 ; send error message
  915.         ret                             ; and exit
  916. srdel2: mov     si,offset srvbuf        ; set pointer for crun
  917.         call    crun
  918.          nop
  919.          nop
  920.          nop
  921. srdel3: mov     ah,'Y'                  ; return an ack
  922.         mov     pack.datlen,0           ; no data
  923.         mov     trans.chklen,1          ; reply with 1 char checksum
  924.         call    pktsize                 ; report packet size
  925.         call    spack
  926.          nop
  927.          nop
  928.          nop
  929.         ret
  930. srvdel  endp
  931.  
  932. ; serspc - handle other side's request of Remote Space  [jrd]
  933. srvspc  proc    near
  934.         test    denyflg,spcflg          ; is command enabled?
  935.         jz      srspc1                  ; z = yes
  936.         mov     bx,offset remms9        ; else give a message
  937.         mov     trans.chklen,1          ; reply with 1 char checksum
  938.         call    errpack                 ; back to local kermit
  939.         ret
  940. srspc1: mov     dl,0                    ; use current drive
  941.         mov     ah,36h                  ; get disk free space
  942.         int     dos                     ; ax = sectors/cluster
  943.         cmp     ax,0ffffh               ; invalid drive indicator?
  944.         jne     srspc2                  ; ne = no
  945.         mov     di,offset data
  946.         mov     si,offset spcmsg2       ; give Drive not ready message
  947.         call    strcpy
  948.         jmp     short srspc3            ; send it
  949. srspc2: mul     bx                      ; sectors/cluster * clusters = sectors
  950.         mul     cx                      ; bytes = sectors * bytes/sector
  951.         mov     di,offset data          ; destination
  952.         mov     word ptr [di],0d0ah     ; cr/lf
  953.         mov     word ptr[di+2],'  '     ; space space
  954.         add     di,4                    ; start number here
  955.         call    lnout                   ; convert number to asciiz in [di]
  956.         mov     si,offset spcmsg        ; trailer of message
  957.         call    strcat                  ; tack onto end of number part
  958. srspc3: mov     trans.chklen,1          ; reply with 1 char checksum
  959.         mov     dx,offset data
  960.         call    strlen                  ; get data size into cx for doenc
  961.         call    doenc                   ; encode
  962.         mov     ah,'Y'                  ; reply with an ack
  963.         call    pktsize                 ; report packet size
  964.         call    spack                   ; send it, expect no response
  965.          nop                            ; ignore errors
  966.          nop
  967.          nop
  968.         ret
  969. srvspc  endp
  970.  
  971. ; srvwho - respond to remote host's WHO command. [jrd]
  972. srvwho  proc    near
  973.         mov     si,offset whomsg        ; add brief msg of just us chickens
  974.         mov     di,offset data          ; packet's data field
  975.         call    strcpy                  ; copy msg to pkt
  976.         mov     dx,si                   ; strlen works on dx
  977.         call    strlen
  978.         mov     trans.chklen,1          ; reply with 1 char checksum
  979.         mov     ah,'Y'                  ; reply with an ack
  980.         mov     pack.datlen,cx          ; length
  981.         call    pktsize                 ; report packet size
  982.         call    spack                   ; send it, expect no response
  983.          nop                            ; ignore errors
  984.          nop
  985.          nop
  986.         ret
  987. srvwho  endp
  988.  
  989. ; srvmsg - respond to remote host's Message (Send) command
  990. ;  show message on our screen. [jrd]
  991. srvsen  proc    near
  992.         test    denyflg,sndflg          ; is command enabled?
  993.         jnz     srvsen1                 ; nz = yes
  994.         cmp     pack.datlen,1           ; Any data in the packet?
  995.         jbe     srvsen1                 ; e = no, just ack the message.
  996.         cmp     data,'M'                ; Message packet?
  997.         jne     srvsen1                 ; ne = no, ack and forget
  998.         mov     data,' '                ; remove the 'M'
  999.         mov     data+1,' '              ; and byte count field
  1000.         call    dodec                   ; Decode data
  1001.         call    ctlu                    ; clear the line
  1002.         mov     dx,offset data+2   ; Where the reply is. (skip M and byte cnt)
  1003.         call    prtasz                  ; Print it on the screen
  1004. srvsen1:mov     ah,'Y'                  ; reply with an ack
  1005.         mov     pack.datlen,0           ; length
  1006.         mov     trans.chklen,1          ; reply with 1 char checksum
  1007.         call    pktsize                 ; report packet size
  1008.         call    spack                   ; send it, expect no response
  1009.          nop                            ; ignore errors
  1010.          nop
  1011.          nop
  1012.         ret
  1013. srvsen  endp
  1014.  
  1015.  
  1016. ; srvhos - handle other side's request of REM Host command-line. [jrd]
  1017. ; We execute the command with STDOUT redirected to $kermit$.tmp and then
  1018. ; read and transmit that file to the other end. No such file results in
  1019. ; returning just an error msg ACK packet
  1020. srvhos  proc    near
  1021.         test    denyflg,hostflg         ; command enabled?
  1022.         jz      srvhos2                 ; z = yes
  1023.         mov     trans.chklen,1          ; reply with 1 char checksum
  1024.         mov     bx,offset remms9        ; else give a message
  1025.         call    errpack                 ; back to local kermit
  1026.         jmp     rskp
  1027.  
  1028. srvhos2:mov     si,offset data          ; received filename, asciiz from rpack
  1029.         mov     di,offset srvbuf        ; destination
  1030.         call    strcpy                  ; copy data to srvbuf
  1031.         mov     si,offset srvtmp    ; add redirection tag of " >$kermit$.tmp"
  1032.         call    strcat
  1033.         mov     si,offset srvbuf        ; si = pointer for crun
  1034.         call    crun                    ; go do the command
  1035.          nop
  1036.          nop
  1037.          nop
  1038.         mov     si,offset srvtmp+2      ; get name of temp file
  1039.         mov     di,offset diskio.string ; destination
  1040.         call    strcpy                  ; copy it to diskio.string
  1041.         mov     ax,di                   ; filename pointer for isfile
  1042.         call    isfile                  ; did we make the temp file?
  1043.         jnc     srhos1                  ; nc = yes
  1044.         mov     trans.chklen,1          ; reply with 1 char checksum
  1045.         mov     bx,offset remms10       ; else give a message
  1046.         call    errpack                 ; back to local kermit
  1047.         call    pktsize                 ; report packet size
  1048.         jmp     rskp                    ; and exit
  1049. srhos1: mov     flags.xflg,1            ; say use X rather than F packet
  1050.         mov     pack.state,'R'          ; remember state
  1051.         call    send11                  ; this should send it
  1052.          nop
  1053.          nop
  1054.          nop
  1055.         mov     flags.xflg,0            ; clear flag
  1056.         mov     dx,offset diskio.string
  1057.         mov     ah,del2                 ; delete the temp file
  1058.         int     dos
  1059.         jmp     rskp                    ; return in any case
  1060. srvhos  endp
  1061.  
  1062. ; Respond to other side's request of Remote Help. Write & read $kermit$.tmp
  1063. ; Return rskp. [jrd]
  1064. srvhlp  proc    near
  1065.         mov     si,offset srvtmp+2      ; use filename of $kermit$.tmp
  1066.         mov     di,offset diskio.string ; put name here
  1067.         call    strcpy
  1068.         mov     ah,creat2               ; create the file
  1069.         mov     cx,0                    ; attributes r/w
  1070.         mov     dx,offset diskio.string ; use $kermit$.tmp name
  1071.         int     dos
  1072.         jc      srvhlp4                 ; c = could not open
  1073.         mov     diskio.handle,ax        ; file handle
  1074.         mov     dx,offset hlprem        ; data to be sent, strlen uses dx
  1075.         call    strlen                  ; put string length in cx
  1076.         mov     ah,write2               ; write to file
  1077.         mov     bx,diskio.handle
  1078.         int     dos                     ; write the info
  1079.         pushf                           ; save carry bit
  1080.         mov     ah,close2       ; close the file so we can reread it below
  1081.         mov     bx,diskio.handle
  1082.         int     dos
  1083.         popf                            ; recover carry bit
  1084.         jc      srvhlp4                 ; c = write error, tell remote user
  1085.                                         ; Send temporary file to remote screen
  1086.         mov     flags.xflg,1            ; say use X rather than F packet
  1087.         mov     pack.state,'R'          ; remember state
  1088.         call    send11                  ; this should send it
  1089.          nop
  1090.          nop
  1091.          nop
  1092.         mov     flags.xflg,0            ; clear flag
  1093.         mov     dx,offset diskio.string ; filename
  1094.         mov     ah,del2                 ; delete the temp file
  1095.         int     dos
  1096.         jmp     rskp                    ; and return
  1097.  
  1098. srvhlp4:mov     trans.chklen,1          ; reply with 1 char checksum
  1099.         mov     bx,offset remms3        ; else give a message
  1100.         call    errpack                 ; back to local kermit
  1101.         call    pktsize                 ; report packet size
  1102.         jmp     rskp
  1103. srvhlp  endp
  1104.  
  1105. ; srvini - init parms based on init packet
  1106. srvini  proc    near
  1107.         mov     bx,offset data
  1108.         mov     ax,pack.datlen          ; get number of data bytes
  1109.         call    spar                    ; parse info
  1110.         call    packlen         ; this should really be part of spar, but..
  1111.         mov     bx,offset data
  1112.         call    rpar                    ; setup info about our reception
  1113.         push    ax
  1114.         mov     al,trans.chklen         ; checksum length negotiated
  1115.         mov     curchk,al               ; use as new working length
  1116.         pop     ax
  1117.         mov     al,ah
  1118.         mov     ah,0
  1119.         mov     pack.datlen,ax          ; set size of return info
  1120.         mov     trans.chklen,1          ; reply with 1 char checksum
  1121.         mov     ah,'Y'
  1122.         call    pktsize                 ; report packet size
  1123.         call    spack                   ; send the packet off
  1124.          nop
  1125.          nop
  1126.          nop
  1127.         mov     al,curchk       ; restore checksum length before proceeding
  1128.         mov     trans.chklen,al
  1129.         jmp     rskp                    ; and go succeed
  1130. srvini  endp
  1131.  
  1132. ;       This is the REMOTE command
  1133.  
  1134. REMOTE  PROC    NEAR
  1135.         mov     dx,offset remtab      ; Parse a keyword from the REMOTE table
  1136.         mov     bx,offset remhlp
  1137.         mov     ah,cmkey
  1138.         call    comnd
  1139.          jmp    r
  1140.         call    bx                      ; Call the appropriate routine
  1141.          jmp    r                       ; Command failed
  1142.         jmp     rskp
  1143. REMOTE  ENDP
  1144.  
  1145. ; REMDIS - Get disk usage on remote system
  1146.  
  1147. REMDIS  PROC    NEAR
  1148.         mov     remcmd,'U'              ; Disk usage command
  1149.         mov     rempac,'G'              ; Packet type = generic
  1150.         mov     remlen,0                ; no text required
  1151.         jmp     genric                  ; Execute generic Kermit command
  1152. REMDIS  ENDP
  1153.  
  1154.  
  1155. ; REMHEL - Get help about remote commands
  1156.  
  1157. REMHEL  PROC    NEAR
  1158.         mov     remcmd,'H'              ; Help
  1159.         mov     rempac,'G'              ; Packet type = generic
  1160.         mov     remlen,0                ; no text required
  1161.         jmp     genric                  ; Execute generic Kermit command
  1162. REMHEL  ENDP
  1163.  
  1164. ; REMTYP - Type a remote file
  1165.  
  1166. REMTYP  PROC    NEAR
  1167.         mov     remcmd,'T'              ; Type the file
  1168.         mov     rempac,'G'              ; Packet type = generic
  1169.         mov     remlen,1                ; text required
  1170.         jmp     genric
  1171. REMTYP  ENDP
  1172.  
  1173. ; REMHOS - Execute a remote host command
  1174.  
  1175. REMHOS  PROC    NEAR
  1176.         mov     remcmd,' '              ; Don't need one
  1177.         mov     rempac,'C'              ; Packet type = remote command
  1178.         mov     remlen,1                ; text required
  1179.         jmp     genric
  1180. REMHOS  ENDP
  1181.  
  1182. ; REMKER - Execute a remote Kermit command
  1183.  
  1184. REMKER  PROC    NEAR
  1185.         mov     remcmd,' '              ; Don't need one
  1186.         mov     rempac,'K'              ; Packet type = remote Kermit command
  1187.         mov     remlen,1                ; text required
  1188.         jmp     genric
  1189. REMKER  ENDP
  1190.  
  1191. ; REMDIR - Do a directory
  1192.  
  1193. REMDIR  PROC    NEAR
  1194.         mov     remcmd,'D'
  1195.         mov     rempac,'G'              ; Packet type = generic
  1196.         mov     remlen,0                ; no text required
  1197.         jmp     genric
  1198. REMDIR  ENDP
  1199.  
  1200. ; REMDEL - Delete a remote file
  1201.  
  1202. REMDEL  PROC    NEAR
  1203.         mov     remcmd,'E'
  1204.         mov     rempac,'G'              ; Packet type = generic
  1205.         mov     remlen,1                ; text required
  1206.         jmp     genric
  1207. REMDEL  ENDP
  1208.  
  1209. ; REMCWD - Change remote working directory
  1210.  
  1211. REMCWD  PROC    NEAR
  1212.         mov     remcmd,'C'
  1213.         mov     rempac,'G'              ; Packet type = generic
  1214.         mov     remlen,0                ; no text required
  1215.         jmp     genric
  1216. REMCWD  ENDP
  1217.  
  1218. ; REMLOGIN - LOGIN [username [password [account]]]
  1219.  
  1220. REMLOGIN PROC   NEAR
  1221.         mov     remcmd,'I'
  1222.         mov     rempac,'G'              ; Packet type = generic
  1223.         mov     remlen,0                ; no text required
  1224.         jmp     genric
  1225. REMLOGIN ENDP
  1226.  
  1227. ; REMMSG - Send one line short message to remote screen. [jrd]
  1228.  
  1229. REMMSG  proc    near
  1230.         mov     remcmd,'M'
  1231.         mov     rempac,'G'
  1232.         mov     remlen,1                ; text required
  1233.         jmp     genric
  1234. REMMSG  endp
  1235.  
  1236. ; REMWHO - ask for list of remote logged on users [jrd]
  1237.  
  1238. REMWHO  proc    near
  1239.         mov     remcmd,'W'
  1240.         mov     rempac,'G'
  1241.         mov     remlen,0                ; no text required
  1242.         jmp     genric
  1243. REMWHO  endp
  1244.  
  1245. ; GENRIC - Send a generic command to a remote Kermit server
  1246.  
  1247. GENRIC  PROC    NEAR
  1248.         mov     bx,offset srvbuf        ; Where to put the text
  1249.         mov     temp,bx                 ; where field starts
  1250.         cmp     rempac,'C'              ; Remote Host command?
  1251.         je      genra                   ; e = yes, no counted string(s)
  1252.         cmp     rempac,'K'              ; Remote Kermit command?
  1253.         je      genra                   ; e = yes, no counted string(s)
  1254.         mov     ah,remcmd               ; get command letter
  1255.         mov     [bx],ah                 ; store in buffer
  1256.         inc     temp                    ; inc to data field
  1257.         add     bx,2                    ; Leave room for type and size
  1258. genra:  mov     ah,cmtxt                ; Parse arbitrary text up to a CR
  1259.         mov     dx,offset genmsg        ; In case they want help
  1260.         call    comnd
  1261.          jmp    r
  1262.          nop
  1263.         mov     al,ah                   ; Don't forget the size
  1264.         mov     ah,0
  1265.         mov     cnt,ax                  ; Save it here
  1266.         add     temp,ax                 ; point to next field
  1267.         cmp     rempac,'C'              ; Remote Host command?
  1268.         je      genra3                  ; e = yes, no counted string(s)
  1269.         cmp     rempac,'K'              ; Remote Kermit command?
  1270.         je      genra3                  ; e = yes, no counted string(s)
  1271.         cmp     al,0                    ; any text?
  1272.         je      genra3                  ; e = no
  1273.         add     al,32                   ; Do the tochar function
  1274.         mov     srvbuf+1,al             ; Size of first field
  1275.         inc     temp                    ; include count byte
  1276. genra3: cmp     al,remlen               ; got necessary command text?
  1277.         jae     genra2                  ; ae = yes
  1278.         mov     ah,prstr
  1279.         mov     dx,offset ermes1        ; need more info
  1280.         int     dos
  1281.         or      errlev,2                ; say cannot receive
  1282.         or      fsta.xstatus,2          ; set status failed
  1283.         mov     kstatus,2               ; global status
  1284.         jmp     rskp
  1285.  
  1286. genra2: mov     flags.xflg,1            ; output coming to screen
  1287.         cmp     rempac,'K'              ; Remote Kermit command?
  1288.         je      genr0                   ; e = yes
  1289.         cmp     rempac,'C'              ; Remote host command?
  1290.         je      genr0                   ; No, skip this part
  1291. genrb:
  1292.         cmp     remcmd,'C'              ; Change working directory?
  1293.         je      genrf                   ; e = yes, ask for password
  1294.         cmp     remcmd,'I'              ; remote login command?
  1295.         je      genrd                   ; e = yes
  1296.         jmp     genr0                   ; neither so no extra prompts here
  1297.  
  1298. genrd:  cmp     cnt,0                   ; have user name already?
  1299.         jne     genrf                   ; ne = yes
  1300.         mov     dx,offset user          ; prompt for username
  1301.         call    prompt
  1302.         mov     bx,offset srvbuf+1      ; skip command letter
  1303.         mov     temp,bx                 ; start of field
  1304.         call    input                   ; Read text
  1305.         jcxz    genr0                   ; z = none
  1306.         mov     temp,bx                 ; point to next data field
  1307.  
  1308. genrf:  mov     dx,offset password      ; Get optional password
  1309.         call    prompt
  1310.         mov     bx,temp                 ; Where to put the password
  1311.         mov     comand.cmquiet,1        ; turn on quiet mode
  1312.         call    input                   ; Read in the password
  1313.         mov     comand.cmquiet,0        ; turn off quiet mode
  1314.         jcxz    genr0                   ; z = no text, do not add field
  1315.         mov     temp,bx                 ; point to next data field
  1316.                                         ;
  1317.         cmp     remcmd,'I'              ; remote login command?
  1318.         jne     genr0                   ; ne = no
  1319.         mov     dx,offset account       ; get optional account ident
  1320.         call    prompt
  1321.         mov     bx,temp                 ; Where this field starts
  1322.         call    input                   ; Read in text
  1323.         jcxz    genr0                   ; z = no text, do not add field
  1324.         mov     temp,bx                 ; point to next data field
  1325.                                         ; All fields completed
  1326. genr0:  mov     ax,temp                 ; pointer to next field
  1327.         sub     ax,offset srvbuf        ; minus start of buffer = data length
  1328.         mov     cnt,ax                  ; remember size here
  1329.         cmp     flags.cxzflg,'C'        ; Control-C entered?
  1330.         jne     genr0a                  ; ne = no
  1331.         ret                             ; return failure
  1332.  
  1333. genr0a: mov     kstatus,0               ; global status
  1334.         mov     pack.numtry,0           ; Initialize count
  1335.         call    ipack                   ; Send init parameters
  1336.          jmp    genr2
  1337.          nop                            ; Make it 3 bytes long
  1338.         mov     ah,trans.chklen
  1339.         mov     curchk,ah               ; Save desired checksum length
  1340.         mov     trans.chklen,1          ; Use 1 char for server functions
  1341.         mov     pack.numrtr,0           ; No retries yet
  1342. genr1:  cmp     pack.state,'A'          ; Did the user type a ^C?
  1343.         je      genr2x
  1344.         mov     ah,pack.numtry
  1345.         cmp     ah,maxtry               ; Too many tries?
  1346.         jl      genr3                   ; Nope, keep trying
  1347. genr2:  mov     ah,prstr
  1348.         mov     dx,offset erms18        ; Print error msg and fail
  1349.         int     dos
  1350. genr2x: mov     ah,curchk
  1351.         mov     trans.chklen,ah         ; Restore
  1352.         mov     flags.xflg,0         ; reset screen output flag before leaving
  1353.         xor     ax,ax                   ; tell statistics this was a read
  1354.         or      errlev,4             ; DOS error level, failure of REMote cmd
  1355.         mov     fsta.xstatus,4          ; set status
  1356.         mov     kstatus,4               ; global status
  1357.         jmp     rskp
  1358. genr3:  push    es                      ; Prepare to put string into packet
  1359.         push    ds
  1360.         pop     es
  1361.         mov     si,offset srvbuf        ; Move from here
  1362.         mov     di,offset data          ; to here
  1363.         mov     cx,cnt                  ; Move this many characters
  1364.         cld
  1365.         rep     movsb                   ; Perform the string move
  1366.         pop     es
  1367.         mov     ax,cnt
  1368.         mov     pack.datlen,ax          ; How much data to send
  1369.         mov     cx,ax                   ; Size of data
  1370.         call    doenc                   ; Encode it
  1371.         inc     pack.numtry             ; Increment number of trials
  1372.         mov     trans.chklen,1          ; use block check 1 to server
  1373.         mov     pack.seqnum,0           ; Packet number 0
  1374.         mov     ah,rempac               ; Packet type
  1375.         call    pktsize                 ; report packet size
  1376.         call    spack                   ; Send the packet
  1377.          jmp    genr2                   ; Tell user we can't do it
  1378.          nop
  1379.         call    rpack                   ; Get ACK (w/o screen stuff)
  1380.          jmp    genr3a                  ; Got a NAK - try again
  1381.          nop
  1382.         jmp     genr3b                  ; Ok
  1383.  
  1384. genr3a: push    ax
  1385.         mov     ah,curchk
  1386.         mov     trans.chklen,ah         ; Restore after reception
  1387.         pop     ax
  1388.         jmp     genr1                   ; NAK, try again
  1389.  
  1390. genr3b: push    ax                      ; Ok
  1391.         mov     ah,curchk
  1392.         mov     trans.chklen,ah         ; Restore after reception
  1393.         pop     ax
  1394.         cmp     ah,'Y'                  ; Is all OK?
  1395.         jne     genr4
  1396.         cmp     pack.datlen,0           ; Any data in the ACK?
  1397.         je      genr31                  ; Nope - just return.
  1398.         call    dodec                   ; Decode data
  1399.         mov     di,offset data          ; Where the reply is
  1400.         mov     cx,pack.datlen          ; How much data we have
  1401.         jcxz    genr31                  ; z = nothing
  1402.         mov     ah,prstr
  1403.         mov     dx,offset crlf          ; start with cr/lf
  1404.         int     dos
  1405.         call    prtscr                  ; Print it on the screen
  1406. genr31: mov     flags.xflg,0    ; reset screen output flag before leaving
  1407.         jmp     rskp                    ; And we're done.
  1408. genr4:  cmp     ah,'X'                  ; Text packet?
  1409.         je      genr5
  1410.         cmp     ah,'S'                  ; Handling this like a file?
  1411.         jne     genr6
  1412.         mov     pack.state,'R'          ; Set the state
  1413.         mov     bx,offset rin21         ; Where to go to
  1414.         jmp     genr51                  ; Continue
  1415. genr5:  mov     pack.state,'F'
  1416.         call    dodec                   ; Decode data
  1417.         mov     bx,offset rfile3        ; Jump to here
  1418. genr51: mov     flags.xflg,1            ; Remember we saw an "X" packet
  1419.         push    ax
  1420.         mov     ah,prstr
  1421.         mov     dx,offset crlf          ; for some systems
  1422.         int     dos
  1423.         pop     ax                      ; keep packet type in ah
  1424.         mov     pack.numtry,0
  1425.         mov     pack.numrtr,0
  1426.         mov     pack.numpkt,0
  1427.         mov     pack.pktnum,0
  1428.         call    begtim                  ; start next statistics group
  1429.         call    bx                      ; Handle it almost like filename
  1430.         call    read2                   ; Receive the rest
  1431.          jmp    r                       ; Oops, we failed
  1432.          nop
  1433.         jmp     rskp                    ; Done OK
  1434. genr6:  cmp     ah,'E'                  ; Error packet?
  1435.         je      genr6x                  ; e = yes
  1436.         jmp     genr1                   ; Try again
  1437. genr6x: call    dodec                   ; Decode data
  1438.         call    error1                  ; Print the error messge
  1439. ;;;;    call    serrst
  1440.         mov     flags.xflg,0    ; reset screen output flag before leaving
  1441.         jmp     rskp                    ; And return
  1442. GENRIC  ENDP
  1443.  
  1444. ; Send  "I" packet with transmission parameters
  1445.  
  1446. IPACK   PROC    NEAR
  1447.         call    serini                  ; Initialize port
  1448.         jc      ipk0x                   ; c = failure
  1449.         call    ihosts                  ; initialize the host
  1450.         mov     pack.pktnum,0           ; Use packet number 0
  1451.         mov     pack.numtry,0           ; Number of retries
  1452.         mov     pack.numrtr,-1          ; no retries (incremented below)
  1453. ipk0:   call    updrtr
  1454.         cmp     pack.state,'A'          ; Did user type a ^C?
  1455.         je      ipk0x                   ; e = yes
  1456.         push    dx
  1457.         mov     dl,imxtry
  1458.         cmp     pack.numtry,dl          ; Reached our limit?
  1459.         pop     dx
  1460.         jl      ipk1                    ; l = no
  1461. ipk0x:  ret                             ; Yes, so we fail
  1462. ipk1:   inc     pack.numtry             ; Save the updated number of tries
  1463.         mov     ah,dtrans.ebquot     ; default 8 bit quote, needed with parity
  1464.         mov     trans.ebquot,ah         ; save as active mode
  1465.         mov     bx,offset data          ; Get a pointer to our data block
  1466.         call    rpar                    ; Set up the parameter information
  1467.         xchg    ah,al
  1468.         mov     ah,0
  1469.         mov     pack.datlen,ax          ; Save the number of arguments
  1470.         mov     pack.seqnum,0           ; Use packet number 0
  1471.         mov     ah,dtrans.seol          ; restore default end-of-line char
  1472.         mov     trans.seol,ah
  1473.         mov     ah,trans.chklen
  1474.         mov     curchk,ah               ; Save real value
  1475.         mov     trans.chklen,1          ; One char for server function
  1476.         call    pktsize                 ; report packet size
  1477.         mov     ah,'I'                  ; "I" packet
  1478.         call    spack                   ; Send the packet
  1479.          jmp    ipk4
  1480.          nop
  1481.         call    rpack                   ; Get a packet
  1482.          jmp    ipk4                    ; Try again
  1483.          nop
  1484.         push    ax
  1485.         mov     ah,curchk
  1486.         mov     trans.chklen,ah         ; Reset
  1487.         pop     ax
  1488.         cmp     ah,'Y'                  ; ACK?
  1489.         jne     ipk3                    ; If not try next
  1490.         mov     ax,pack.pktnum          ; Get the packet number
  1491.         cmp     ax,pack.seqnum          ; Is it the right packet number?
  1492.         je      ipk2
  1493.          jmp    ipk0                    ; If not try again
  1494. ipk2:   mov     ax,pack.datlen          ; Get the number of pieces of data
  1495.         mov     bx,offset data          ; Pointer to the data
  1496. ipk2a:  call    spar                    ; Read in the data
  1497.         mov     ah,trans.chklen
  1498.         mov     curchk,ah               ; This is what we decided on
  1499.         call    packlen                 ; Get max send packet size
  1500.         mov     pack.numtry,0           ; Reset the number of tries
  1501.         jmp     rskp
  1502. ipk3:   cmp     ah,'N'                  ; NAK?
  1503.         jne     ipk3y                   ; Yes, try again
  1504.         jmp     ipk0
  1505. ipk3y:  cmp     ah,'E'                  ; Is it an error packet
  1506.         je      ipk3x
  1507.         jmp     ipk0                    ; Trashed data.
  1508. ipk3x:  mov     ax,0            ; Other side doesn't know about "I" packet
  1509.                                 ; force defaults (zero length response)
  1510.         jmp     ipk2a           ;   to use lowest common denominator
  1511. ipk4:   mov     ah,curchk
  1512.         mov     trans.chklen,ah         ; Reset.
  1513.         cmp     flags.cxzflg,0          ; did user say quit?
  1514.         jne     ipk5                    ; ne = yes, quit
  1515.         jmp     ipk0                    ; Keep trying
  1516. ipk5:   ret
  1517. IPACK   ENDP
  1518.  
  1519. ; Returns CX the count of characters read
  1520. ;         BX the updated pointer to the input buffer
  1521. ;         input buffer = <ascii data length count byte>textstring
  1522. INPUT   PROC    NEAR
  1523.         mov     inpbuf,bx               ; Where to put byte count
  1524.         inc     bx                      ; skip over count byte
  1525.         mov     dx,0                    ; help, none
  1526.         mov     ah,cmtxt                ; get text with embedded whitespace
  1527.         call    comnd
  1528.          jmp    r
  1529.          nop
  1530.         mov     al,ah                   ; length of text
  1531.         mov     ah,0
  1532.         mov     cnt,ax                  ; save here
  1533. input1: push    bx
  1534.         mov     bx,inpbuf
  1535.         mov     [bx],al                 ; store count byte
  1536.         add     byte ptr [bx],32        ; convert to ascii
  1537.         pop     bx                      ; return pointer to next free byte
  1538.         mov     cx,cnt                  ; return byte count
  1539.         ret
  1540. INPUT   ENDP
  1541.  
  1542.  
  1543. ; Jumping to this location is like retskp.  It assumes the instruction
  1544. ;   after the call is a jmp addr
  1545.  
  1546. RSKP    PROC    NEAR
  1547.         pop     bp
  1548.         add     bp,3
  1549.         push    bp
  1550.         ret
  1551. RSKP    ENDP
  1552.  
  1553. ; Jumping here is the same as a ret
  1554.  
  1555. R       PROC    NEAR
  1556.         ret
  1557. R       ENDP
  1558.  
  1559. code    ends
  1560.         end
  1561.  
  1562.  
  1563.